#ifndef FREYABASEEXTENSIONEX_H
#define FREYABASEEXTENSIONEX_H

#include "freyabaseaction.h"
#include "freyabasecontrol.h"
#include "freyalib_global.h"

#include <QTcpServer>
#include <QTcpSocket>
#include <QThread>
#include <QMutex>
#include <QMutexLocker>
#include <QSharedPointer>

class FTcpSocket;
class FreyaPluginPusherEx : public QThread
{
    Q_OBJECT
private:
    explicit FreyaPluginPusherEx(QString PluginID, QHostAddress addr, int port, FreyaBaseControl *pControl, QObject *parent = nullptr);
    ~FreyaPluginPusherEx();

public:
    static FreyaPluginPusherEx *ConnectToPlugin(QString PluginID, QHostAddress addr, int port, FreyaBaseControl *pControl = nullptr, QObject *parent = nullptr);

    void PusherExecute(const FreyaData pData);
    void PusherExecute(QByteArray *pBa);

    QString &FreyaPluginID();

    bool PeerAddress(QHostAddress &objAddress);
signals:
    void ToPluginRequest(const FreyaData pData);
    void ToDisconnected();

private slots:
    void OnConnect();
    void OnReadyRead(const QByteArray &byteData);
    void OnReadyRead(QByteArray *pBa, FreyaData pData, bool pBRet);
    void OnStateChanged(QAbstractSocket::SocketState state);
    void OnPusherExecute(const FreyaData pData);
    void OnPusherExecute(QByteArray *pBa, FreyaData pData, bool pBRet);

private:
    FTcpSocket                          *m_Pusher;
    int                                 m_MsgAuth;
    int                                 m_CmdAuth;
    QString                             m_PluginID;
    QHostAddress                        m_AddrPlugin;
    int                                 m_IPortPlugin;
    FreyaBaseControl                    *m_pControl;
};

class FREYALIBSHARED_EXPORT FreyaExtensionEx : public QTcpServer, public FreyaBaseAction
{
    Q_OBJECT
public:
    explicit FreyaExtensionEx(int port, FreyaBaseControl *pControl = nullptr, const char *actionName = nullptr);
    ~FreyaExtensionEx();
    bool DefineAuthCode(const QStringList &MsgAuth, const QStringList &CmdAuth);
    QList<FreyaPluginPusherEx*> PusherList();

    int PeepAddressList(QList<QHostAddress> &listAddress);

protected:
    virtual void Execute(const FreyaData pData);

private slots:
    void OnPluginRequest();
    void OnReadyRead(const QByteArray &byteData);
    void OnPusherDisconnected();
    void OnPusherRequest(const FreyaData pData);

private:
    static void OnPusherQuery(const FreyaData pData, int waitTime, QObject *sender, FreyaBaseControl *pControl);

private:
    QList<FreyaPluginPusherEx*>         m_PusherList;
    QStringList                         m_WaitPluginIDList;
    FreyaBaseControl                    *m_pControl;
    bool                                m_isListening;
    QMutex                              m_PluginListMutex;
};

#endif // FREYABASEEXTENSIONEX_H
